package com.tengju.bff.interfaces.shared.servlet.realm;

import com.tengju.bff.interfaces.shared.servlet.ServletContextUtil;
import com.tengju.bff.interfaces.shared.servlet.UserServletContext;
import com.tengju.user.application.shared.ApplicationException;
import com.tengju.user.application.shared.ApplicationExceptionCode;
import com.tengju.user.domain.model.chief.*;
import com.tengju.user.domain.model.club.Club;
import com.tengju.user.domain.model.club.ClubId;
import com.tengju.user.domain.model.club.ClubRepository;
import com.tengju.user.domain.model.login.LoginResult;
import com.tengju.user.domain.model.login.SsoToken;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.service.SsoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class SsoRealm extends AuthorizingRealm {


    @Autowired
    private SsoService ssoService;
    @Autowired
    private ChiefClubRepository chiefClubRepository;
    @Autowired
    private ChiefGenSecRelationRepository chiefGenSecRelationRepository;
    @Autowired
    private ClubRepository clubRepository;
    @Autowired
    private UserInfoRepository userInfoRepository;

    @Value("${sso.manage.role.code}")
    private String manageRoleCode;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof SsoToken;
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        UserServletContext servletContext = ServletContextUtil.getServletContext();
        Set<String> roles = new HashSet<>();
        String url = servletContext.getRequestPath();

        if (url.startsWith("/boss/")) {
            //sso权限校验
            String method = servletContext.getRequest().getMethod();
            LoginResult loginResult = (LoginResult)principalCollection.getPrimaryPrincipal();
            boolean hasPermission = ssoService.checkPermission(new StaffId(loginResult.getUserId()), url, method);
            if (hasPermission) {
                roles.add("sso");
            }
        }
        return new SimpleAuthorizationInfo(roles);

    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        String token = (String) auth.getCredentials();

        if (StringUtils.isEmpty(token)) {
            throw ApplicationException.error(ApplicationExceptionCode.TOKEN_OVERDUE);
        }

        LoginResult result = ssoService.checkToken(token);
        if (result == null) {
            throw ApplicationException.error(ApplicationExceptionCode.TOKEN_OVERDUE);
        }

        ChiefId chiefId = new ChiefId(result.getUserId());
        List<ClubId> clubIdList;
        List<UserIdCode> genSecIdCodeList;
        //腾炬管理角色 拥有所有俱乐部 sec权限
        if (result.getRoleCodes().contains(manageRoleCode)) {
            List<Club> clubs = clubRepository.queryAll();
            clubIdList = clubs.stream().map(Club::getClubId).collect(Collectors.toList());
            List<UserInfo> userInfos = userInfoRepository.queryByStarLevel(List.of(StarLevelEnum.SEC, StarLevelEnum.EEC));
            genSecIdCodeList = userInfos.stream().map(UserInfo::getIdCode).collect(Collectors.toList());
        } else {
            List<ChiefClub> chiefClubList = chiefClubRepository.getChiefClub(chiefId);
            clubIdList = chiefClubList.stream()
                    .map(ChiefClub::getClubId)
                    .collect(Collectors.toList());
            List<ChiefGenSecRelation> chiefGenSecRelation = chiefGenSecRelationRepository.getChiefGenSecRelation(chiefId);
            genSecIdCodeList = chiefGenSecRelation.stream()
                    .map(ChiefGenSecRelation::getGenSecIdCode)
                    .collect(Collectors.toList());
        }
        result.setClubIdList(clubIdList);
        result.setGenSecIdCodeList(genSecIdCodeList);
        return new SimpleAuthenticationInfo(result,token,getName());
    }
}
